﻿#include "flutter_blue_event_handler.h"
#include <flutter/encodable_value.h>
#include "flutter_blue_utils.h"
#include "flutter_blue_device_agent.h"
#include "flutter_blue_utils.h"
// 构造函数实现
FlutterEventHandler::FlutterEventHandler(SendMessageConnectorCall messageConnectorCall, LogToFlutterCall logToFlutterCall)
	: messageConnectorCall_(messageConnectorCall)
	, logToFlutterCall_(logToFlutterCall) {
	// 初始化其他成员变量
	event_scan_handler = std::make_unique<EventStreamHandler<>>();
}

// 蓝牙扫描回调
void FlutterEventHandler::BluetoothLEWatcher_Received(
	BluetoothLEAdvertisementWatcher sender,
	BluetoothLEAdvertisementReceivedEventArgs args) {
	try {
		auto manufacturer_data = Utils::parseManufacturerData(args.Advertisement());

		auto bluetoothAddress = args.BluetoothAddress();
		auto localName = args.Advertisement().LocalName();

		// 将 GUID 转换为字符串列表
		flutter::EncodableList serviceUuids;
		for (auto&& uuid : args.Advertisement().ServiceUuids()) {
			serviceUuids.push_back(flutter::EncodableValue(Utils::to_uuidstr(uuid)));
		}

		auto name = localName;
		// 构造扫描结果
		event_scan_handler->Success(
			EncodableMap{
					{"name",             winrt::to_string(name)},
					{"deviceId",         std::to_string(bluetoothAddress)},
					{"manufacturerData", manufacturer_data},
					{"rssi",             args.RawSignalStrengthInDBm()},
					// TODO
					{"serviceUuids",     serviceUuids},
			});
	}
	catch (...) {
		// 处理异常
		event_scan_handler->Error("0", "error", nullptr);
	}
}

// 启动扫描
void FlutterEventHandler::StartScan() {
	if (!bluetoothLEWatcher) {
		bluetoothLEWatcher = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher();
		bluetoothLEWatcher.ScanningMode(winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEScanningMode::Active);
		bluetoothLEWatcherReceivedToken = bluetoothLEWatcher.Received({ this, &FlutterEventHandler::BluetoothLEWatcher_Received });
	}
	bluetoothLEWatcher.Start();
}

// 停止扫描
void FlutterEventHandler::StopScan() {
	if (bluetoothLEWatcher) {
		bluetoothLEWatcher.Stop();
		bluetoothLEWatcher.Received(bluetoothLEWatcherReceivedToken);
	}
	bluetoothLEWatcher = nullptr;
}

//蓝牙连接
winrt::fire_and_forget FlutterEventHandler::ConnectAsync(uint64_t bluetoothAddress) {
	try {
		logToFlutterCall_("ConnectAsync " + std::to_string(bluetoothAddress));
		auto device = co_await
			BluetoothLEDevice::FromBluetoothAddressAsync(bluetoothAddress);
		/*auto servicesResult = co_await
		device.GetGattServicesAsync();
		if (servicesResult.Status() != GattCommunicationStatus::Success) {
			logToFlutterCall_("GetGattServicesAsync error: ");
			sendMessageConnector(EncodableMap{
					{"type",     "OnConnectionStateChanged"},
					{"success",  true},
					{"deviceId", std::to_string(bluetoothAddress)},
					{"data",     "disconnected"},
			});
			co_return;
		}*/
		logToFlutterCall_("ConnectAsync 2    " + std::to_string(bluetoothAddress));
		auto connectionStatusChangedToken = device.ConnectionStatusChanged({ this, &FlutterEventHandler::BluetoothLEDevice_ConnectionStatusChanged });
		auto deviceAgent = std::make_unique<BluetoothDeviceAgent>(device, connectionStatusChangedToken, [device, this](int newMtu) {
			messageConnectorCall_(
				EncodableMap{
						{"type",     "OnMtuChange"},
						{"success",  true},
						{"deviceId", std::to_string(device.BluetoothAddress())},
						{"data",     newMtu + 3},// 加上 L2CAP 头部大小
				}
				);
			});
		logToFlutterCall_("ConnectAsync 3   " + std::to_string(bluetoothAddress));
		//deviceAgent->initGattSession();
		logToFlutterCall_("ConnectAsync 4   " + std::to_string(bluetoothAddress));
		auto pair = std::make_pair(bluetoothAddress, std::move(deviceAgent));
		connectedDevices.insert(std::move(pair));

		messageConnectorCall_(EncodableMap{
				{"type",     "OnConnectionStateChanged"},
				{"success",  true},
				{"deviceId", std::to_string(bluetoothAddress)},
				{"data",     "connected"},
			});
	}
	catch (const winrt::hresult_error& e) {
		logToFlutterCall_("Error connecting to device: " + winrt::to_string(e.message()));
	}
	catch (...) {
		messageConnectorCall_(EncodableMap{
				{"type",     "OnConnectionStateChanged"},
				{"success",  false},
				{"deviceId", std::to_string(bluetoothAddress)},
				{"data",     "disconnected"},
			});
	}
}


// 蓝牙连接状态改变
void FlutterEventHandler::BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args) {
	logToFlutterCall_("ConnectionStatusChanged " + std::to_string((int32_t)sender.ConnectionStatus()) + "  deviceId=" + std::to_string(sender.BluetoothAddress()));
	if (sender.ConnectionStatus() == BluetoothConnectionStatus::Disconnected) {
		//这里不能调用，可能会发生闪退，连接的时候可能立马收到关闭，然后又收到连接，导致一些异常问题
		// [log] 原生日志打印 ConnectionStatusChanged 1  deviceId=106026653640166
		// 2025 - 01 - 17 11:18 : 13.672 蓝牙  断开连接 null null null
		// [log] 原生日志打印 ConnectionStatusChanged 0  deviceId = 106026653640166
		// [log] 接收到原生消息{ data: disconnected, deviceId : 106026653640166, success : true, type : OnConnectionStateChanged }
		// [log] 原生日志打印 ConnectionStatusChanged 1  deviceId = 106026653640166
		//CleanConnection(sender.BluetoothAddress(), false);
		messageConnectorCall_(EncodableMap{
			   {"type",     "OnConnectionStateChanged"},
			   {"success",  true},
			   {"deviceId", std::to_string(sender.BluetoothAddress())},
			   {"data",     "disconnected"},
			});
	}
}

//断开连接
void FlutterEventHandler::CleanConnection(uint64_t bluetoothAddress, bool dispose) {
	try {
		auto node = connectedDevices.extract(bluetoothAddress);
		if (!node.empty()) {
			auto deviceAgent = std::move(node.mapped());
			// 关闭设备（如果需要）
			if (dispose) {
				deviceAgent->device.Close();
				deviceAgent->Close();
			}

		}
		messageConnectorCall_(EncodableMap{
				{"type",     "OnConnectionStateChanged"},
				{"success",  true},
				{"deviceId", std::to_string(bluetoothAddress)},
				{"data",     "disconnected"},
			});
	}
	catch (const std::exception& e) {
		// 捕获所有从 std::exception 派生的异常
		messageConnectorCall_(EncodableMap{
				{"type",         "OnConnectionStateChanged"},
				{"success",      false},
				{"deviceId",     std::to_string(bluetoothAddress)},
				{"errorMessage", e.what()}  // 获取异常消息
			});
	}
	catch (...) {
		messageConnectorCall_(EncodableMap{
				{"type",     "OnConnectionStateChanged"},
				{"success",  false},
				{"deviceId", std::to_string(bluetoothAddress)},
			});
	}

}

//这个设备是否连接
boolean FlutterEventHandler::HaveConnectedDevices(uint64_t deviceId) {
	auto it = connectedDevices.find(deviceId);
	if (it == connectedDevices.end()) {
		return false;
	}
	return true;
}
//这个设备是否连接
BluetoothDeviceAgent* FlutterEventHandler::GetConnectedDevices(uint64_t deviceId) {
	auto it = connectedDevices.find(deviceId);
	if (it != connectedDevices.end()) {
		return it->second.get();  // 返回 unique_ptr 管理的指针
	}
	return nullptr;  // 设备未找到，返回 nullptr
}
//发现服务内部异步
winrt::fire_and_forget FlutterEventHandler::DiscoverServicesAsync(BluetoothDeviceAgent* bluetoothDeviceAgent) {
	std::string deviceId = std::to_string(bluetoothDeviceAgent->device.BluetoothAddress());
	try {
		//初始化
		co_await
			bluetoothDeviceAgent->LoadInit();
		// 确保设备已连接,在发现服务后才能是连接
		if (bluetoothDeviceAgent->device == nullptr || bluetoothDeviceAgent->device.ConnectionStatus() != BluetoothConnectionStatus::Connected) {
			messageConnectorCall_(
				EncodableMap{
						{"type",     "OnDiscoveredServices"},
						{"success",  false},
						{"deviceId", deviceId}
				}
			);
			co_return;
		}
		//是否有服务
		if (bluetoothDeviceAgent->gattServices.size() == 0) {
			//再次重试
			co_await
				bluetoothDeviceAgent->LoadInit();
		}
		if (bluetoothDeviceAgent->device == nullptr || bluetoothDeviceAgent->device.ConnectionStatus() != BluetoothConnectionStatus::Connected) {
			messageConnectorCall_(
				EncodableMap{
						{"type",     "OnDiscoveredServices"},
						{"success",  false},
						{"deviceId", deviceId}
				}
			);
			co_return;
		}
		//是否有服务
		if (bluetoothDeviceAgent->gattServices.size() == 0) {
			messageConnectorCall_(
				EncodableMap{
						{"type",     "OnDiscoveredServices"},
						{"success",  true},
						{"deviceId", deviceId},
						{"data",     flutter::EncodableMap()}
				}
			);
			co_return;
		}
		flutter::EncodableMap servicesFlutter;
		// 遍历服务与特征，返回数据
		for (auto const& servicesCharacteristic : bluetoothDeviceAgent->gattServicesCharacteristics) {
			flutter::EncodableList characteristicsFlutter;
			//服务UUID
			winrt::hstring serviceUuid = servicesCharacteristic.first;
			std::string serviceUuidStdStr = winrt::to_string(serviceUuid);
			//这个服务下的全部特征
			std::map <winrt::hstring, GattCharacteristic> characteristics = servicesCharacteristic.second;
			//循环特征
			for (auto const& characteristic1 : characteristics) {
				GattCharacteristic characteristic = characteristic1.second;
				// 获取特征属性
				GattCharacteristicProperties props = characteristic.CharacteristicProperties();
				std::string propString = Utils::properties_to_string(props);
				// 创建特征信息映射
				flutter::EncodableMap characteristicInfo{
						std::make_pair("uuid", Utils::to_uuidstr(characteristic.Uuid())),
						std::make_pair("deviceId", deviceId),
						std::make_pair("serviceUuid", serviceUuidStdStr),
						std::make_pair("properties", propString)
				};
				// 添加描述符信息
				flutter::EncodableList descriptors;
				for (auto const& descriptor : characteristic.GetDescriptors(GUID())) {
					descriptors.push_back(Utils::to_uuidstr(descriptor.Uuid()));
				}
				characteristicInfo.insert({ "descriptors", descriptors });

				characteristicsFlutter.push_back(characteristicInfo);
			}
			servicesFlutter.insert({ serviceUuidStdStr, characteristicsFlutter });

		}
		// 发送服务及特性信息
		messageConnectorCall_(
			EncodableMap{
					{"type",     "OnDiscoveredServices"},
					{"success",  true},
					{"deviceId", deviceId},
					{"data",     servicesFlutter}
			}
		);
	}
	catch (const winrt::hresult_error& e) {
		logToFlutterCall_("Error discovering services: " + winrt::to_string(e.message()));
	}
	catch (...) {
		messageConnectorCall_(
			EncodableMap{
					{"type",     "OnDiscoveredServices"},
					{"success",  false},
					{"deviceId", deviceId},
			}
			);
	}
}

//设置通知
winrt::fire_and_forget FlutterEventHandler::SetNotifiableAsync(BluetoothDeviceAgent* bluetoothDeviceAgent, std::string service, std::string characteristic, std::string bleInputProperty){
	std::string deviceId = std::to_string(bluetoothDeviceAgent->device.BluetoothAddress());
	hstring serviceHs = to_hstring(service);
	hstring characteristicHs = to_hstring(characteristic);
	try {
		GattCharacteristic gattCharacteristic = co_await
			bluetoothDeviceAgent->GetCharacteristicAsync(serviceHs, characteristicHs);
		auto descriptorValue = bleInputProperty == "notification" ? GattClientCharacteristicConfigurationDescriptorValue::Notify
			: bleInputProperty == "indication" ? GattClientCharacteristicConfigurationDescriptorValue::Indicate
			: GattClientCharacteristicConfigurationDescriptorValue::None;
		auto writeDescriptorStatus = co_await
			gattCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(descriptorValue);
		if (writeDescriptorStatus != GattCommunicationStatus::Success) {
			messageConnectorCall_(EncodableMap{
					{"type",           "OnSetNotifyChanged"},
					{"success",        false},
					{"deviceId",       deviceId},
					{"service",        service},
					{"characteristic", characteristic},
					{"data",           bleInputProperty},
				});
			co_return;
		}
		//            logToFlutter(("WriteClientCharacteristicConfigurationDescriptorAsync ");

		//        if (bleInputProperty != "disabled") {
		//            // 设置 ValueChanged 回调，并传递额外参数
		//            bluetoothDeviceAgent.valueChangedTokens[characteristic] = gattCharacteristic.ValueChanged({this, &FlutterBluePlugin::GattCharacteristic_Received});
		//        } else {
		//            gattCharacteristic.ValueChanged(std::exchange(bluetoothDeviceAgent.valueChangedTokens[characteristic], {}));
		//        }
		if (bleInputProperty != "disabled") {
            // 使用 lambda 表达式捕获额外参数，并传递给 GattCharacteristic_Received
            bluetoothDeviceAgent->valueChangedTokens[serviceHs][characteristicHs] = gattCharacteristic.ValueChanged(
                [this, bluetoothDeviceAgent, service, characteristic](auto&& sender, auto&& args) {
                    this->GattCharacteristic_Received(bluetoothDeviceAgent, sender, args, service, characteristic);
                }
            );
        }
		else {
			// 如果禁用，则移除事件处理器
			gattCharacteristic.ValueChanged(std::exchange(bluetoothDeviceAgent->valueChangedTokens[serviceHs][characteristicHs], {}));
		}
		messageConnectorCall_(EncodableMap{
				{"type",           "OnSetNotifyChanged"},
				{"success",        true},
				{"deviceId",       deviceId},
				{"service",        service},
				{"characteristic", characteristic},
				{"data",           bleInputProperty},
			});
	}
	catch (...) {
		messageConnectorCall_(EncodableMap{
				{"type",           "OnSetNotifyChanged"},
				{"success",        false},
				{"deviceId",       deviceId},
				{"service",        service},
				{"characteristic", characteristic},
				{"data",           bleInputProperty},
			});
	}
}

//通过执行读取或写入操作来触发 MTU 协商。Windows 会自动处理 MTU 协商过程
winrt::fire_and_forget FlutterEventHandler::RequestMtuAsync(BluetoothDeviceAgent* bluetoothDeviceAgent, uint64_t expectedMtu) {
	std::string deviceId = std::to_string(bluetoothDeviceAgent->device.BluetoothAddress());
	try {
		logToFlutterCall_("RequestMtuAsync expectedMtu");
		auto gattSession = co_await
			GattSession::FromDeviceIdAsync(bluetoothDeviceAgent->device.BluetoothDeviceId());

		messageConnectorCall_(EncodableMap{
				{"type",     "OnMtuChanged"},
				{"success",  true},
				{"deviceId", deviceId},
				{"data",     (int64_t)gattSession.MaxPduSize()},
			});
	}
	catch (...) {
		messageConnectorCall_(EncodableMap{
				{"type",     "OnMtuChanged"},
				{"success",  false},
				{"deviceId", deviceId},
			});
	}
}

//读取特征值

winrt::fire_and_forget FlutterEventHandler::ReadValueAsync(BluetoothDeviceAgent* bluetoothDeviceAgent, std::string service, std::string characteristic) {
	std::string deviceId = std::to_string(bluetoothDeviceAgent->device.BluetoothAddress());
	hstring serviceHs = to_hstring(service);
	hstring characteristicHs = to_hstring(characteristic);
	try {
		auto gattCharacteristic = co_await
			bluetoothDeviceAgent->GetCharacteristicAsync(serviceHs, characteristicHs);
		auto readValueResult = co_await
			gattCharacteristic.ReadValueAsync();
		auto bytes = Utils::to_bytevc(readValueResult.Value());
		//            OutputDebugString((L"ReadValueAsync " + winrt::to_hstring(characteristic) + L", " + winrt::to_hstring(Utils::to_hexstring(bytes)) + L"\n").c_str());
		messageConnectorCall_(EncodableMap{
				{"type",           "OnDescriptorRead"},
				{"success",        true},
				{"deviceId",       deviceId},
				{"service",        service},
				{"characteristic", characteristic},
				{"data",           bytes},
			});
	}
	catch (...) {
		messageConnectorCall_(EncodableMap{
				{"type",           "OnDescriptorRead"},
				{"success",        false},
				{"deviceId",       deviceId},
				{"service",        service},
				{"characteristic", characteristic},
			});
	}
}
//写入特征值
winrt::fire_and_forget FlutterEventHandler::WriteValueAsync(BluetoothDeviceAgent* bluetoothDeviceAgent, std::string service, std::string characteristic, std::vector <uint8_t> value, std::string bleOutputProperty) {
	std::string deviceId = std::to_string(bluetoothDeviceAgent->device.BluetoothAddress());
	hstring serviceHs = to_hstring(service);
	hstring characteristicHs = to_hstring(characteristic);
	try {
		GattCharacteristic gattCharacteristic = co_await
			bluetoothDeviceAgent->GetCharacteristicAsync(serviceHs, characteristicHs);
		GattWriteOption writeOption = bleOutputProperty.compare("withoutResponse") == 0 ? GattWriteOption::WriteWithoutResponse : GattWriteOption::WriteWithResponse;
		// 打印 writeOption
		std::string optionString = (writeOption == GattWriteOption::WriteWithoutResponse)
			? "WriteWithoutResponse"
			: "WriteWithResponse";

		GattCommunicationStatus status = co_await
			gattCharacteristic.WriteValueAsync(Utils::from_bytevc(value), writeOption);
		//            OutputDebugString(
		//                    (L"WriteValueAsync " + winrt::to_hstring(characteristic) + L", " + winrt::to_hstring(to_hexstring(value)) + L", " + winrt::to_hstring((int32_t) writeValueStatus) + L"\n").c_str());
					// 检查写入状态
		if (status == GattCommunicationStatus::Success) {
			logToFlutterCall_("WriteValueAsync success,writeOption:" + optionString);
		}
		else {
			logToFlutterCall_("WriteValueAsync failed with status: " + std::to_string(static_cast<int32_t>(status)));
		}
	}
	catch (...) {
		logToFlutterCall_("WriteValueAsync error");
	}
}

void FlutterEventHandler::GattCharacteristic_Received(BluetoothDeviceAgent* bluetoothDeviceAgent, GattCharacteristic sender, GattValueChangedEventArgs args, std::string service,
	std::string characteristic) {
	std::string deviceId = std::to_string(bluetoothDeviceAgent->device.BluetoothAddress());
	auto uuid = Utils::to_uuidstr(sender.Uuid());
	try {
		auto bytes = Utils::to_bytevc(args.CharacteristicValue());
		//            OutputDebugString((L"GattCharacteristic_Received " + winrt::to_hstring(uuid) + L", " + winrt::to_hstring(to_hexstring(bytes)) + L"\n").c_str());
		messageConnectorCall_(EncodableMap{
				{"type",           "OnCharacteristicReceived"},
				{"success",        true},
				{"deviceId",       deviceId},
				{"service",        service},
				{"characteristic", uuid},
				{"data",           bytes},
			});
	}
	catch (...) {
		messageConnectorCall_(EncodableMap{
				{"type",           "OnCharacteristicReceived"},
				{"success",        false},
				{"deviceId",       deviceId},
				{"service",        service},
				{"characteristic", uuid},
			});
	}
}